﻿namespace Gmantis.Controls.DataGrid
{
    internal class DataGridFocusAndEditingManager
    {
        // Methods
        public DataGridFocusAndEditingManager(DataGridModel model)
        {
            this.Model = model;
            this.CurrentColumn = null;
            this.CurrentRow = null;
            this.IsEditingCell = false;
            this.IsEditingRow = false;
        }

        public bool BeginEdit()
        {
            DataGridCell currentEditingCell = this.CurrentEditingCell;
            if (((this.CurrentColumn == null) || (this.CurrentRow == null)) || this.IsEditingCell)
            {
                return false;
            }
            this.IsEditingCell = true;
            DataGridCell cell2 = this.CurrentEditingCell;
            PropertyChangedEventArgs<DataGridCell> e = new PropertyChangedEventArgs<DataGridCell>
            {
                NewValue = cell2,
                OldValue = currentEditingCell
            };
            this.Model.OnCurrentEditingCellChanged(e);
            return true;
        }

        public bool BeginEditRow()
        {
            DataGridRow currentEditingRow = this.CurrentEditingRow;
            if (((this.CurrentColumn == null) || (this.CurrentRow == null)) || this.IsEditingRow)
            {
                return false;
            }
            this.IsEditingRow = true;
            DataGridRow row2 = this.CurrentEditingRow;
            if (row2 != currentEditingRow)
            {
                PropertyChangedEventArgs<DataGridRow> e = new PropertyChangedEventArgs<DataGridRow>
                {
                    NewValue = row2,
                    OldValue = currentEditingRow
                };
                this.Model.OnCurrentEditingRowChanged(e);
            }
            return true;
        }

        private bool ClearCurrentCell(bool preserveRow, bool preserveColumn)
        {
            DataGridCell currentCell = this.CurrentCell;
            DataGridColumn currentColumn = this.CurrentColumn;
            DataGridRow currentRow = this.CurrentRow;
            if (!preserveColumn)
            {
                currentColumn = null;
            }
            if (!preserveRow)
            {
                currentRow = null;
            }
            if (this.OnCurrentCellChanging(currentCell, this.Model.DataGrid[currentRow, currentColumn]))
            {
                this.CurrentColumn = currentColumn;
                this.CurrentRow = currentRow;
                this.IsEditingCell = false;
                this.OnCurrentRowOrColumnChanged(currentCell, this.CurrentCell);
                return true;
            }
            return false;
        }

        public void ClearCurrentColumn()
        {
            this.ClearCurrentCell(true, false);
        }

        public void ClearCurrentEditingCell()
        {
            DataGridCell currentEditingCell = this.CurrentEditingCell;
            this.IsEditingCell = false;
            if (currentEditingCell != null)
            {
                PropertyChangedEventArgs<DataGridCell> e = new PropertyChangedEventArgs<DataGridCell>
                {
                    NewValue = null,
                    OldValue = currentEditingCell
                };
                this.Model.OnCurrentEditingCellChanged(e);
            }
        }

        public void ClearCurrentEditingRow()
        {
            DataGridRow currentEditingRow = this.CurrentEditingRow;
            this.IsEditingRow = false;
            if (currentEditingRow != null)
            {
                PropertyChangedEventArgs<DataGridRow> e = new PropertyChangedEventArgs<DataGridRow>
                {
                    NewValue = null,
                    OldValue = currentEditingRow
                };
                this.Model.OnCurrentEditingRowChanged(e);
            }
        }

        public void ClearCurrentRow()
        {
            this.ClearCurrentCell(false, true);
        }

        private bool OnCurrentCellChanging(DataGridCell oldValue, DataGridCell newValue)
        {
            if (oldValue != newValue)
            {
                PropertyChangingEventArgs<DataGridCell> e = new PropertyChangingEventArgs<DataGridCell>
                {
                    OldValue = oldValue,
                    NewValue = newValue
                };
                this.Model.OnCurrentCellChanging(e);
                return !e.Cancel;
            }
            return true;
        }

        private bool OnCurrentRowOrColumnChanged(DataGridCell oldValue, DataGridCell newValue)
        {
            PropertyChangedEventArgs<DataGridCell> e = new PropertyChangedEventArgs<DataGridCell>
            {
                OldValue = oldValue,
                NewValue = newValue
            };
            this.Model.OnCurrentCellChanged(e);
            this.Model.DataGrid.OnCurrentRowOrColumnChanged(new DataGridCellEventArgs(newValue));
            return true;
        }

        public bool SetCurrentCell(DataGridCell cell)
        {
            if (cell.DataGrid != this.Model.DataGrid)
            {
                return false;
            }
            DataGridCell newValue = cell;
            DataGridCell currentCell = this.CurrentCell;
            if (newValue != currentCell)
            {
                if (!this.OnCurrentCellChanging(currentCell, newValue))
                {
                    return false;
                }
                if (cell == null)
                {
                    this.ClearCurrentCell(false, true);
                }
                else
                {
                    this.SetCurrentColumn(cell.Column, false);
                    this.SetCurrentRow(cell.Row, false);
                }
                if (this.OnCurrentRowOrColumnChanged(currentCell, newValue))
                {
                    this.ClearCurrentEditingCell();
                }
            }
            return true;
        }

        public bool SetCurrentColumn(DataGridColumn column)
        {
            return this.SetCurrentColumn(column, true);
        }

        private bool SetCurrentColumn(DataGridColumn column, bool raiseCellChanged)
        {
            if (column.DataGrid != this.Model.DataGrid)
            {
                return false;
            }
            DataGridCell currentCell = this.CurrentCell;
            if (column != this.CurrentColumn)
            {
                if (raiseCellChanged && !this.OnCurrentCellChanging(currentCell, this.Model.DataGrid[this.CurrentRow, column]))
                {
                    return false;
                }
                this.CurrentColumn = column;
                if (raiseCellChanged)
                {
                    this.OnCurrentRowOrColumnChanged(currentCell, this.CurrentCell);
                }
            }
            return true;
        }

        public bool SetCurrentRow(DataGridRow row)
        {
            return this.SetCurrentRow(row, true);
        }

        private bool SetCurrentRow(DataGridRow row, bool raiseCellChanged)
        {
            if (row.DataGrid != this.Model.DataGrid)
            {
                return false;
            }
            DataGridCell currentCell = this.CurrentCell;
            if (row != this.CurrentRow)
            {
                if (raiseCellChanged && !this.OnCurrentCellChanging(currentCell, this.Model.DataGrid[row, this.CurrentColumn]))
                {
                    return false;
                }
                this.CurrentRow = row;
                if (raiseCellChanged)
                {
                    this.OnCurrentRowOrColumnChanged(currentCell, this.CurrentCell);
                }
            }
            return true;
        }

        // Properties
        public DataGridCell CurrentCell
        {
            get
            {
                if ((this.CurrentColumn != null) && (this.CurrentRow != null))
                {
                    return this.Model.DataGrid[this.CurrentRow, this.CurrentColumn];
                }
                return null;
            }
        }

        public DataGridColumn CurrentColumn { get; private set; }

        public DataGridCell CurrentEditingCell
        {
            get
            {
                if (((this.CurrentColumn != null) && (this.CurrentRow != null)) && this.IsEditingCell)
                {
                    return this.Model.DataGrid[this.CurrentRow, this.CurrentColumn];
                }
                return null;
            }
        }

        public DataGridRow CurrentEditingRow
        {
            get
            {
                if (((this.CurrentColumn != null) && (this.CurrentRow != null)) && this.IsEditingRow)
                {
                    return this.CurrentRow;
                }
                return null;
            }
        }

        public DataGridRow CurrentRow { get; private set; }

        private bool IsEditingCell { get; set; }

        private bool IsEditingRow { get; set; }

        private DataGridModel Model { get; set; }
    }
}
